<template>
  <li
    :class="classes"
    @click.stop="select"
    v-show="isShow"
    @mouseenter="toggDelOperation"
    @mouseleave="toggDelOperation"
    @mousedown.prevent
  ><!-- <div :style="spaceStyle"></div> -->
    <e-icon
      v-if="isShowArrowIcon"
      type="arrow-down"
      :class="treeIconClasses"
      @click.stop="arrowClick">
    </e-icon>
    <div
      v-else
      class="haloe-select-item-none-icon"></div>
    <slot>{{ showLabel }}</slot>
    <e-icon
      v-if="isShowDelIcon"
      @click.stop="deleteOperation"
      type="delete"
      class="haloe-select-item-delete-icon"></e-icon>
  </li>
</template>
<script>
import mixinsForm from '../../mixins/form';
import { findComponentUpward } from '../../utils/assist';
import random from '../../utils/random_str';
import { getCurrentInstance } from 'vue';
import { nextTick } from 'vue';
import bus from 'vue3-eventbus'
const prefixCls = 'haloe-select-item';
export default {
  name: 'eOption',
  componentName: 'select-item',
  mixins: [ mixinsForm ],
  emits: ['on-select-selected'],
  inject: {
    SelectInstance: {
      default: null
    },
    OptionGroupInstance: {
      default: null
    }
  },
  props: {
    level: {
      type: Number,
      default: -1,
    },
    isOpen: {
      type: Boolean,
      default: true,
    },
    textOffset: {
      type: Number,
      default: 22,
    },
    hasChild: {
      type: Boolean,
      default: false,
    },
    indeterminate: {
      type: Boolean,
      default: false,
    },
    value: {
      type: [String, Number],
      required: true
    },
    label: {
      type: [String, Number]
    },
    disabled: {
      type: Boolean,
      default: false
    },
    // 4.0.0
    tag: {
      type: [String, Number]
    }
  },
  data () {
    return {
      searchLabel: '',  // the slot value (textContent)
      autoComplete: false,
      id: random(6),
      instance: null,
      rootParent: {},
      isShowDelIcon: false,
    };
  },
  computed: {
    isShowArrowIcon() {
      return this.hasChild
    },
    treeIconClasses() {
      return [
        `${prefixCls}-tree-icon`,
        {
          [`${prefixCls}-tree-icon-open`]: this.isOpen,
        },
      ]
    },
    classes () {
      return [
        `${prefixCls}`,
        {
          [`${prefixCls}-disabled`]: this.itemDisabled,
          [`${prefixCls}-selected`]: this.selected && !this.autoComplete,
          [`${prefixCls}-focus`]: this.isFocused
        }
      ];
    },
    showLabel () {
      return (this.label) ? this.label : this.value;
    },
    optionLabel(){
      return this.label || (this.$el && this.$el.textContent);
    },
    isFocused(){
      const SelectInstance = this.SelectInstance;
      let slotOptions = SelectInstance.slotOptions || [];
      const focusIndex = SelectInstance.focusIndex;
      // when autoComplete the slotsOption index sort error
      // use the parent default slots to get right slotsOption index
      const defaultSlot = SelectInstance.$slots.default;
      if (this.autoComplete && defaultSlot) {
        slotOptions = [];
        let vNodes = defaultSlot();
        while(vNodes.length > 0) {
          const vNode = vNodes.shift();
          if (vNode.type && typeof vNode.type === 'object' && vNode.type.name ==='eOption' ) {
            slotOptions.push(vNode);
          }else {
            if (Array.isArray(vNode.children)) {
              vNodes = vNodes.concat(vNode.children)
            }
          }           
        }
      }
      const focusOption = slotOptions[focusIndex]
      return focusOption && focusOption.props && focusOption.props.value === this.value;
    },
    isShow(){
      const SelectInstance = this.SelectInstance;
      const filterable = SelectInstance.filterable;
      const query = SelectInstance.query.toLowerCase().trim();
      const filterByLabel = SelectInstance.filterByLabel;
      const slotOptionsMap = SelectInstance.slotOptionsMap;
      const { props } = slotOptionsMap.get(this.value) || { props: {} };
      const label = this.label || this.$el && this.$el.textContent
      let filterOption = (label || props.value || '').toLowerCase();
      if (filterByLabel) {
        filterOption = (label || '').toLowerCase();
      }
      const showFilterOption = filterOption.includes(query);
      return !filterable || filterable && showFilterOption
    },
    selected(){
      const SelectInstance = this.SelectInstance;
      const values = SelectInstance.values || [];
      return values.find(item => item.value === this.value)
    }
  },
  methods: {
    toggDelOperation() {
      if (this.rootParent.allowDelete) {
        this.isShowDelIcon = !this.isShowDelIcon
      }
    },
    deleteOperation() {
      if (!this.rootParent.allowDelete) {
        return
      }
      bus.emit('on-select-deleted', {
        value: this.value,
        label: this.optionLabel,
        tag: this.tag
      })
    },
    arrowClick() {
      this.dispatch('eSelect', 'on-tree-switch', {
        value: this.value,
        label: this.optionLabel,
        tag: this.tag,
      })
      this.$emit('on-tree-switch', {
        value: this.value,
        label: this.optionLabel,
        tag: this.tag,
      })
    },
    select () {
      if (this.itemDisabled) return false;
      const { values, multiple, limited } = this.SelectInstance
      if (multiple && values && values.length >= limited) return
      this.SelectInstance.handleOnSelectSelected({
        value: this.value,
        label: this.optionLabel,
        tag: this.tag
      });
    },
    addOption () {
      const select = this.SelectInstance;
      const group = this.OptionGroupInstance;
      const {id, value, instance} = this;
      if (group) {
        group.optionList.push({
          ...instance,
          id,
          tag: 'option'
        });
      }
      if (select){
        select.slotOptions.push({
          ...instance,
          id,
          tag: 'option'
        });
        // console.log("--------", select.slotOptions)
        select.slotOptionsMap.set(value, instance)
        // fix Option hide, the modalValue cannot selected
        const { modelValue } = select;
        modelValue && modelValue.length && select.lazyUpdateValue(true);
      }
    },
    removeOption () {
      const group = this.OptionGroupInstance;
      const select = this.SelectInstance;
      const {id, value} = this;
      if (group) {
        const index = group.optionList.findIndex(item => item.id === id);
        index !== -1 && group.optionList.splice(index, 1);
      }
      if( select ){
        const select = this.SelectInstance;
        const index = select.slotOptions.findIndex(item => item.id === id);
        index !== -1 && select.slotOptions.splice(index, 1);
        select.slotOptionsMap.has(value) && select.slotOptionsMap.delete(value);
      }
    }
  },
  created(){
    this.instance = getCurrentInstance();
  },
  mounted () {
    this.addOption();
    const eSelect = findComponentUpward(this, 'eSelect');
    if (eSelect) {
      this.autoComplete = eSelect.autoComplete;
    }
    this.rootParent = eSelect
  },
  beforeUnmount () {
    // fix AutoComplete. when suggest the word, the dropdown will hide
    nextTick(() => {
      this.removeOption();
      this.instance = null;
    })
  }
};
</script>